/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.sh.ndt.user.mbean;

import com.sh.ndt.common.CreateXML;
import com.sh.ndt.common.SessionObjects;
import com.sh.ndt.common.URL;
import com.sh.ndt.common.WSCaller;
import com.sh.ndt.course.entity.Course;
import com.sh.ndt.exam.entity.Exam;
import com.sh.ndt.exam.entity.ExamScheduleDetail;
import com.sh.ndt.exam.entity.TestHistory;
import com.sh.ndt.exam.entity.TestHistoryParam;
import com.sh.ndt.schedule.entity.ExamScheduleParam;
import com.sh.ndt.user.entity.UserDashboardDetail;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import org.apache.log4j.Logger;
import org.primefaces.context.RequestContext;
import org.primefaces.event.SelectEvent;
import org.primefaces.event.TabChangeEvent;

/**
 *
 * @author Prashanth
 */
@ManagedBean(name = "registeredUsersDashboardBean")
@SessionScoped
public class RegisteredUsersDashboardBean implements Serializable {

    private static final long serialVersionUID = 1L;

    private static final Logger LOGGER = Logger.getLogger(RegisteredUsersDashboardBean.class);

    private List<Course> courseList = new ArrayList<Course>();
    private int selectedCourse = 0;
    private Date scheduleDate = null;
    private Exam examDetail = null;
    private UserDashboardDetail userDashboardDetail = new UserDashboardDetail();

    private Date maxScheduleDate = null;
    private Date minScheduleDate = null;
    private SessionObjects sob = null;

    private List<TestHistory> testHistoryList = new ArrayList<TestHistory>();

    public RegisteredUsersDashboardBean() {

        /**
         * TO DO; this is temporary, this need to be removed
         */
        Course course1 = new Course(1, "RT Level 2", 900.00);
        Course course2 = new Course(2, "RT Level 3", 550.00);

        this.courseList.add(course1);
        this.courseList.add(course2);

        /**
         * This is placed in constructor because every this bean is called, this
         * needs to reset.
         *
         * User calendar object to set the schedule date range Add today to
         * calendar Add 30 Days to calendar Assign it to Max Schedule Date
         * Assign today to Min Schedule Dat
         */
        Calendar cal = new GregorianCalendar();
        Date date = new Date();
        cal.setTime(date);
        cal.add(Calendar.DATE, 30);
        date = cal.getTime();
        LOGGER.debug("Max Schedule End Date::: " + date);
        this.setMaxScheduleDate(date);
        this.setMinScheduleDate(new Date());

        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        SessionObjects sob1 = (SessionObjects) externalContext.getSessionMap().get("SESSION_OBJECT");

        LOGGER.debug("SESSION Object: " + sob1);

        this.setSob(sob1);

    }

    /**
     * @return the courseList
     */
    public List<Course> getCourseList() {
        return courseList;
    }

    /**
     * @param courseList the courseList to set
     */
    public void setCourseList(List<Course> courseList) {
        this.courseList = courseList;
    }

    /**
     * @return the selectedCourse
     */
    public int getSelectedCourse() {
        return selectedCourse;
    }

    /**
     * @param SelectedCourse the selectedCourse to set
     */
    public void setSelectedCourse(int selectedCourse) {
        this.selectedCourse = selectedCourse;
    }

    public void handleDateSelect(SelectEvent event) {
        SimpleDateFormat format = new SimpleDateFormat("d/M/yyyy");
        LOGGER.debug((Date) event.getObject());
        LOGGER.debug(this.scheduleDate);

        Date today = new Date();
        LOGGER.debug("Date Comparision Status: " + this.scheduleDate.compareTo(today));
        if (this.scheduleDate.compareTo(today) < 0) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Incorrect Date Selection", "Exam Date cannot be less than today, please select new exam date"));
        }
    }

    /**
     * @return the scheduleDate
     */
    public Date getScheduleDate() {
        return scheduleDate;
    }

    /**
     * @param scheduleDate the scheduleDate to set
     */
    public void setScheduleDate(Date scheduleDate) {
        this.scheduleDate = scheduleDate;
    }

    public void showTestHistory() {
        Map<String, String> params;
        params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();

        int testId = Integer.parseInt(params.get("testId"));
        LOGGER.debug("Test Id: " + testId);
        Map<String, Object> options = new HashMap<String, Object>();
        options.put("modal", true);
        options.put("draggable", false);
        options.put("resizable", false);
        options.put("contentWidth", 760);
        options.put("width", 800);
        options.put("height", 450);

        /**
         * Empty the previous data from data table
         */
        this.setTestHistoryList(null);

        /**
         * Load test history data from WS call Here getTestHistoryList call a WS
         * at /examService/getTestHistory
         */
        this.setTestHistoryList(getTestHistoryList(this.sob.getUser().getUserId(), testId));

        RequestContext.getCurrentInstance().openDialog("showTestHistory", options, null);
    }

    public void scheduleExam() {
        /**
         * Validate whether the exam is already scheduled
         */
        if (!validateCourseSelection()) {
            return;
        }

        String inputXml = null;

        LOGGER.debug("**********Inside scheduleExam()*******");
        LOGGER.debug("Schedule Date: " + this.scheduleDate);
        LOGGER.debug("Selected Course: " + this.selectedCourse);
        LOGGER.debug("User Id: " + sob.getUser().getUserId());
        LOGGER.debug("**************************************");

        ExamScheduleParam examScheduleParam = new ExamScheduleParam();

        examScheduleParam.setCourseId(selectedCourse);
        examScheduleParam.setScheduleDate(scheduleDate);
        examScheduleParam.setUserId(sob.getUser().getUserId());

        inputXml = CreateXML.generateExamScheduleParamXML(examScheduleParam);
        LOGGER.debug(inputXml);

        WSCaller wsCaller = new WSCaller();
        try {
            UserDashboardDetail userDashboardDetail2 = wsCaller.callAddExamScheduleWS(URL.WS_URL_ADD_EXAM_SCHEDULE, inputXml);

            if (userDashboardDetail != null) {

                /**
                 * Update the dashboard details here... This will act as db
                 * cache update every time
                 */
                SessionObjects sessionObject = this.getSob();
                sessionObject.setUserDashboardDetail(userDashboardDetail2);
                FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("SESSION_OBJECT", sessionObject);
                
                 
                this.setUserDashboardDetail(userDashboardDetail2);

                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Schedule Status: ", "Exam has been scheduled on " + scheduleDate));
            } else {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Schedule Status: Failure", "Error occured while scheduling the exam, please contact application administrator."));
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Schedule Status: Failure", "Error occured while scheduling the exam, please contact application administrator."));
        }
    }

    public void refreshDashboard() {

        LOGGER.debug("SOB:: " + getSob());
        LOGGER.debug(getSob().getUserDashboardDetail().getExamDetail().getExamId());
        LOGGER.debug(getSob().getUserDashboardDetail().getExamDetail().getExamName());
        LOGGER.debug(getSob().getUserDashboardDetail().getMockTestAttepts());
        LOGGER.debug(getSob().getUserDashboardDetail().getCreditedPoints());
        LOGGER.debug(getSob().getUserDashboardDetail().getDaysLeftForExam());
        //LOGGER.debug(getSob().getUserDashboardDetail().getExamScheduleList().get(0).getNextScheduleDate());

        this.setExamDetail(getSob().getUserDashboardDetail().getExamDetail());
        this.setUserDashboardDetail(getSob().getUserDashboardDetail());

    }

    /**
     * @return the examDetail
     */
    public Exam getExamDetail() {
        return examDetail;
    }

    /**
     * @param examDetail the examDetail to set
     */
    public void setExamDetail(Exam examDetail) {
        this.examDetail = examDetail;
    }

    /**
     * @return the userDashboardDetail
     */
    public UserDashboardDetail getUserDashboardDetail() {
        return userDashboardDetail;
    }

    /**
     * @param userDashboardDetail the userDashboardDetail to set
     */
    public void setUserDashboardDetail(UserDashboardDetail userDashboardDetail) {
        this.userDashboardDetail = userDashboardDetail;
    }

    public String launchGeneralMockTest() {
        LOGGER.debug("Inside LaunchMockTest: Launching General Test");
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        getSob().setExamId(2);
        getSob().setExamType("General Mock");
        getSob().setExamTimeLimit(300); // in seconds
        externalContext.getSessionMap().put("SESSION_OBJECT", getSob());
        return "questionBoard.xhtml?faces-redirect=true";
    }

    public String launchSpecificMockTest() {
        LOGGER.debug("Inside LaunchMockTest: Launching Specific Test");
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        getSob().setExamId(2);
        getSob().setExamType("Specific Mock");
        getSob().setExamTimeLimit(120); // in seconds
        externalContext.getSessionMap().put("SESSION_OBJECT", getSob());
        return "questionBoard.xhtml?faces-redirect=true";
    }

    public String launchGeneralExam() {
        LOGGER.debug("Inside LaunchExam");
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        getSob().setExamId(1);
        getSob().setExamType("General");
        getSob().setExamTimeLimit(300); // in seconds
        externalContext.getSessionMap().put("SESSION_OBJECT", getSob());
        return "questionBoard.xhtml?faces-redirect=true";
    }

    public String launchSpecificExam() {
        LOGGER.debug("Inside LaunchExam: Specific Exam");
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        getSob().setExamId(1);
        getSob().setExamType("Specific");
        getSob().setExamTimeLimit(120); // in seconds
        externalContext.getSessionMap().put("SESSION_OBJECT", getSob());

        return "questionBoard.xhtml?faces-redirect=true";
    }

    /**
     * @return the maxScheduleDate
     */
    public Date getMaxScheduleDate() {
        return maxScheduleDate;
    }

    /**
     * @param maxScheduleDate the maxScheduleDate to set
     */
    private void setMaxScheduleDate(Date maxScheduleDate) {
        this.maxScheduleDate = maxScheduleDate;
    }

    /**
     * @return the minScheduleDate
     */
    public Date getMinScheduleDate() {
        return minScheduleDate;
    }

    /**
     * @param minScheduleDate the minScheduleDate to set
     */
    private void setMinScheduleDate(Date minScheduleDate) {
        this.minScheduleDate = minScheduleDate;
    }

    public void handleCourseSelect() {
        validateCourseSelection();
    }

    private boolean validateCourseSelection() {
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        SessionObjects sob = (SessionObjects) externalContext.getSessionMap().get("SESSION_OBJECT");

        LOGGER.debug("**************************************" + this.getSob().isR2ready());

        if (!this.getSob().isR2ready() && this.getSelectedCourse() == 2) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Course Schedule: Failure", "R3 cannot be scheduled without clearing R2"));
            return false;
        }

        LOGGER.debug("**************************************");
        LOGGER.debug("Selected Course is : " + this.getSelectedCourse());
        LOGGER.debug("User Id: " + sob.getUser().getUserId());
        LOGGER.debug("**************************************");
        long courseId = this.getSelectedCourse();
        for (ExamScheduleDetail examlist : sob.getUserDashboardDetail().getExamScheduleList()) {
            if (examlist.getExamId() == courseId) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Course Schedule: Failure", "You have already scheduled for " + examlist.getExamName() + " exam."));
                return false;
            }
        }
        return true;
    }

    public void onTabChange(TabChangeEvent event) {
        LOGGER.debug("Active Tab : " + event.getTab().getId());
    }

    /**
     * @return the sob
     */
    public SessionObjects getSob() {
        return sob;
    }

    /**
     * @param sob the sob to set
     */
    private void setSob(SessionObjects sob) {
        this.sob = sob;
    }

    /**
     * @return the testHistoryList
     */
    public List<TestHistory> getTestHistoryList() {
        return testHistoryList;
    }

    /**
     * @param testHistoryList the testHistoryList to set
     */
    public void setTestHistoryList(List<TestHistory> testHistoryList) {
        this.testHistoryList = testHistoryList;
    }

    private List<TestHistory> getTestHistoryList(int userId, int testId) {

        TestHistoryParam testHistoryParam = new TestHistoryParam();
        testHistoryParam.setUserId(userId);
        testHistoryParam.setTestId(testId);

        String inputXml = CreateXML.generateTestHistoryParamXML(testHistoryParam);
        LOGGER.debug(inputXml);

        WSCaller wsCaller = new WSCaller();

        try {
            return wsCaller.callGetTestHistoryWS(URL.WS_URL_GET_TEST_HISTORY, inputXml);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }
}
